package middleware

import (
	"arc_srv4/common"
	"arc_srv4/database"
	"arc_srv4/logutils"
	"arc_srv4/utils"
	"crypto/sha1"
	"encoding/base64"
	"encoding/hex"
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"github.com/satori/go.uuid"
	"go.uber.org/zap"
	"strings"
	"time"
)

type JwtCustomClaims struct {
	jwt.StandardClaims
}

type CommonRespond struct {
	IB      int    `json:"ib"`
	Message string `json:"message"`
}

// 获取用户
func CheckUser(appKey string, appSecret string) (pond CommonRespond) {

	// 验证用户存在
	strSql := "select * from t_api_user where ifnull(status,0) = 1 and appKey = ? limit 0,1"
	res, err := database.Db.Engine.SQL(strSql, appKey).QueryString()

	if err != nil || len(res) <= 0 {
		pond.IB = common.Http10001
		pond.Message = common.Http10001Desc
		return
	}

	// 验证secret是否合法
	phone := res[0]["phone"]
	a := fmt.Sprintf("%s%s%s", common.JwtCfg.Secret, appKey, phone)
	if appSecret != base64.StdEncoding.EncodeToString([]byte(SetSHA1(a))) {
		pond.IB = common.Http10007
		pond.Message = common.Http10007Desc
		return
	}

	// 验证用户key secret是否对应
	strSql = "select * from t_api_user where ifnull(status,0) = 1 and appKey = ? and appSecret = ?"
	res, err = database.Db.Engine.SQL(strSql, appKey, appSecret).QueryString()

	if err != nil {
		pond.IB = common.Http10002
		pond.Message = common.Http10002Desc
		return
	}

	// 输出
	pond.IB = common.Http200
	pond.Message = common.Http200Desc
	return
}

// 检查API调用次数
func CheckApiTimes(appKey, api string) (pond CommonRespond) {
	// 获取API配置参数
	strSql := "select * from t_api_settings where appKey = ? and api = ? limit 0,1"
	res, err := database.Db.Engine.SQL(strSql, appKey, api).QueryString()

	// 默认当天10次，总共1000次
	dayTimes, allTimes := 10, 1000
	if err == nil && len(res) > 0 {
		dayTimes, allTimes = utils.StringToInt(res[0]["times"]), utils.StringToInt(res[0]["allTimes"])
	}

	checkDay, checkTotal := 0, 0
	// 获取当天调用次数
	strSql = "select count(1) as total from t_api_log where appKey = ? and createDate = ?"
	dayTotal, err := database.Db.Engine.SQL(strSql, appKey, time.Now().Format("2006-01-02")).QueryString()
	if err == nil && len(res) > 0 {
		checkDay = utils.StringToInt(dayTotal[0]["total"])
	}

	// 获取总调用次数
	strSql = "select count(1) as total from t_api_log where appKey = ?"
	allTotal, err := database.Db.Engine.SQL(strSql, appKey).QueryString()
	if err == nil && len(res) > 0 {
		checkTotal = utils.StringToInt(allTotal[0]["total"])
	}
	// 一天次数限制
	if checkDay > dayTimes {
		pond.IB = common.Http10005
		pond.Message = common.Http10005Desc
		return
	}
	// 总次数限制
	if checkTotal > allTimes {
		pond.IB = common.Http10011
		pond.Message = common.Http10011Desc
		return
	}

	// 输出
	pond.IB = common.Http200
	pond.Message = common.Http200Desc
	return
}

// 插入调用日志
func InsertTimes(appKey, api string) error {
	_, err := database.Db.Engine.Exec("insert into t_api_log(appKey,api,createDate,createTime)values(?,?,?,?)",
		appKey, api,
		time.Now().Format("2006-01-02"),
		time.Now().Format("2006-01-02 15:04:05"))

	if err != nil {
		logutils.Logger.Error("insert t_api_log error", zap.String("appKey", appKey), zap.String("api", api), zap.Error(err))
		return err
	}
	logutils.Logger.Info("insert t_api_log success", zap.String("appKey", appKey), zap.String("api", api))
	return nil
}

// 生成appKey appSecret
func GenKeySecret(phone string) (appKey, appSecret string) {
	u1 := uuid.NewV4()
	appKey = strings.ReplaceAll(u1.String(), "-", "")
	a := fmt.Sprintf("%s%s%s", common.JwtCfg.Secret, appKey, phone)
	appSecret = base64.StdEncoding.EncodeToString([]byte(SetSHA1(a)))
	return
}

// sha1算法
func SetSHA1(value string) string {
	shaX := sha1.New()
	shaX.Write([]byte(value))
	return hex.EncodeToString(shaX.Sum([]byte("")))
}

func GetExpired(appKey string) int64 {
	// 验证用户存在
	strSql := "select * from t_api_user where ifnull(status,0) = 1  and appKey = ? limit 0,1"
	res, err := database.Db.Engine.SQL(strSql, appKey).QueryString()

	expired := common.JwtCfg.Expire
	if err != nil || len(res) <= 0 {
		return expired
	}
	expired = int64(utils.StringToInt(res[0]["expired"]))
	if expired <= 0 {
		expired = common.JwtCfg.Expire
	}
	return expired
}

// 生成jwtToken
func GenToken(secret string, appKey string, expireTime int64) (tokenString string, err error) {
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"appKey": appKey,
		"expire": time.Now().Add(time.Duration(expireTime) * time.Second).Unix(),
	})
	tokenString, err = token.SignedString([]byte(secret))
	if err != nil {
		return "", err
	} else {
		return tokenString, nil
	}
}

// 解析 token
func ParseToken(tokenSrt string, SecretKey []byte) (token *jwt.Token, err error) {
	token, err = jwt.Parse(tokenSrt, func(*jwt.Token) (interface{}, error) {
		return SecretKey, nil
	})
	return
}
